﻿namespace Ruirun.Mes
{
    public partial class MesService
    {
        /// <summary>
        /// 获取 实体仓储对象
        /// </summary>
        private MaterialCategoryStore MaterialCategoryStore => ServiceProvider.GetService<MaterialCategoryStore>();

        /// <summary>
        /// 获取 实体查询数据集
        /// </summary>
        public IQueryable<MaterialCategory> MaterialCategorys => MaterialCategoryStore.Entities;

        /// <summary>
        /// 根据编号查找
        /// </summary>
        /// <param name="id">数据实体编号</param>
        /// <returns>业务操作结果</returns>
        public async Task<OperationResult<MaterialCategoryOutputDto>> FindMaterialCategoryById(Guid id)
        {
            Check.NotEmpty(id, nameof(id));

            var outputDto = MaterialCategorys.Where(o => o.Id.Equals(id)).ToOutput<MaterialCategory, MaterialCategoryOutputDto>().FirstOrDefault();
            if (outputDto != null)
            {
                return await Task.FromResult(new OperationResult<MaterialCategoryOutputDto>(OperationResultType.Success, "OK", outputDto));
            }

            return await Task.FromResult(new OperationResult<MaterialCategoryOutputDto>(OperationResultType.NotFound, "Not Found", outputDto));
        }

        /// <summary>
        /// 新增
        /// </summary>
        /// <param name="dtos">DTO信息</param>
        /// <returns>业务操作结果</returns>
        public async Task<OperationResult> CreateMaterialCategorys(params MaterialCategoryInputDto[] dtos)
        {
            return await MaterialCategoryStore.InsertByDtoAsync(dtos);
        }

        /// <summary>
        /// 更新
        /// </summary>
        /// <param name="dtos">DTO信息</param>
        /// <returns>业务操作结果</returns>
        public async Task<OperationResult> UpdateMaterialCategorys(params MaterialCategoryInputDto[] dtos)
        {
            return await MaterialCategoryStore.UpdateByDtoAsync(dtos);
        }

        /// <summary>
        /// 更新
        /// </summary>
        /// <param name="ids">数据实体编号</param>
        /// <returns>业务操作结果</returns>
        public async Task<OperationResult> DeleteMaterialCategorys(params Guid[] ids)
        {
            ids.CheckNotNullOrEmpty(nameof(ids));
            ids.ToList().ForEach(id =>
            {
                //子类别检验
                var children = MaterialCategoryStore.Entities.Count(a => a.ParentId == id);
                if (children > 0)
                {
                    throw new Exception("当前物料存有子类别");
                }
                //关联ipn检验
                var ipn = IPNStore.Entities.Count(a => a.MaterialCategoryId == id);
                if (ipn > 0)
                {
                    throw new Exception("当前物料存有依赖IPN表单");
                }
            });

            return await MaterialCategoryStore.DeleteAsync(ids);
        }

        /// <summary>
        /// 新增
        /// </summary>
        /// <param name="entity">实体信息</param>
        /// <returns>业务操作结果</returns>
        public async Task<OperationResult> CreateMaterialCategory(MaterialCategory entity)
        {
            var exist = MaterialCategoryStore.CheckExists(a => a.Name == entity.Name && a.ParentId == entity.ParentId);
            if (exist) return OperationResult.Error($"当前分类下已存在该类别名称");

            var result = await MaterialCategoryStore.InsertAsync(entity);
            if (!result.Succeeded) return result.ToOperationResult();

            var parent = MaterialCategoryStore.Entities.Where(a => Equals(a.Id, entity.ParentId))
                  .Select(a => new { a.Id, a.TreePathString }).FirstOrDefault();

            string treePathString = string.Empty;
            if (parent == null)
            {
                treePathString = TreeHelper.FormatTreePathString(entity.Id);
            }
            else
            {
                treePathString = TreeHelper.GetTreePathString(entity.Id, parent.TreePathString);
            }
            entity.TreePathString = treePathString;

            var result1 = await MaterialCategoryStore.UpdateAsync(entity);
            if (!result1.Succeeded)
            {
                return result1;
            }

            return result;
        }

        /// <summary>
        /// 更新
        /// </summary>
        /// <param name="entity">DTO信息</param>
        /// <returns>业务操作结果</returns>
        public async Task<OperationResult> UpdateMaterialCategory(MaterialCategory entity)
        {
            var exist = MaterialCategoryStore.CheckExists(a => a.Name == entity.Name && a.ParentId == entity.ParentId, entity.Id);
            if (exist) return OperationResult.Error($"当前分类下已存在该类别名称");


            var existEntity = MaterialCategoryStore.Entities.FirstOrDefault(a => a.Id == entity.Id);
            if (existEntity == null)
            {
                if (existEntity == null) return OperationResult.Error(string.Format("父类别 {0} 不存在", existEntity.Id));
            }

            var parent = MaterialCategoryStore.Entities.Where(a => Equals(a.Id, entity.ParentId))
                  .Select(a => new { a.Id, a.TreePathString }).FirstOrDefault();

            string treePathString = string.Empty;
            if (parent == null)
            {
                treePathString = TreeHelper.FormatTreePathString(entity.Id);
            }
            else
            {
                treePathString = TreeHelper.GetTreePathString(entity.Id, parent.TreePathString);
            }
            existEntity.TreePathString = treePathString;
            existEntity.Name = entity.Name;
            existEntity.Description = entity.Description;
            existEntity.ParentId = entity.ParentId;
            var result = await MaterialCategoryStore.UpdateAsync(existEntity);
            if (result.Succeeded)
            {
                //若父级变更且存在子级，同步更新子级
                if (!Equals(existEntity.TreePathString, entity.TreePathString))
                {
                    var children = MaterialCategoryStore.Entities.Where(o => Equals(o.ParentId, existEntity.Id)).ToList();
                    if (children?.Count > 0)
                    {
                        foreach (var child in children)
                        {
                            var result2 = await UpdateMaterialCategory(child);
                            if (!result2.Succeeded)
                            {
                                return result2;
                            }
                        }
                    }
                }

                return OperationResult.Success((object)entity);
            }

            return result;
        }

    }
}